package com.flashcash.kotlin.router.interceptor

import android.content.Context
import android.text.TextUtils
import com.alibaba.android.arouter.facade.Postcard
import com.alibaba.android.arouter.facade.annotation.Interceptor
import com.alibaba.android.arouter.facade.callback.InterceptorCallback
import com.alibaba.android.arouter.facade.template.IInterceptor
import com.flashcash.solu.app.App
import com.flashcash.solu.common.TokenManager
import com.hwangjr.rxbus.annotation.Subscribe
import com.hwangjr.rxbus.thread.EventThread
import com.flashcash.kotlin.auth.accountKit.CancelLoginEvent
import com.flashcash.kotlin.auth.accountKit.FailLoginEvent
import com.flashcash.kotlin.auth.accountKit.LoginEventBus
import com.flashcash.kotlin.auth.accountKit.SuccessLoginEvent
import com.flashcash.kotlin.router.RouteExtraConst
import com.x.leo.apphelper.log.XLog
import org.jetbrains.anko.runOnUiThread

/**
 * Created by linchen on 21/03/2018.
 */

@Interceptor(priority = 7)
class LoginInterceptor : IInterceptor {
    internal lateinit var mContext: Context

    private var callback: InterceptorCallback? = null
    private var postcard: Postcard? = null

    /**
     * The operation of this interceptor.
     *
     * @param postcard meta
     * @param callback cb
     */
    override fun process(postcard: Postcard, callback: InterceptorCallback) {
        if (postcard.extra and RouteExtraConst.IsNeedLogin == RouteExtraConst.IsNeedLogin) {
            // if the followings are true, start login flow
            // 1. the route requires login
            // 2. user is not currently logged in
            if (!isLogin()) {
                this.callback = callback
                this.postcard = postcard
                postcard.timeout = Int.MAX_VALUE

                // start login flow & subscribe login success fail message
                App.instance.runOnUiThread {
                    try {
                        LoginEventBus.instance.register(this@LoginInterceptor)
                    } catch (ex: Exception) {
                        // IllegalArgumentException maybe thrown if the bus is already unsubscribed, which we do not care
                        // in any exception we do not crash
                        XLog.e("e: ", ex, 10)
                    }
                    App.instance.currentActivity?.toLogin()
                }
            } else {
                callback.onContinue(postcard)
            }
        } else {
            callback.onContinue(postcard)
        }
    }

    /**
     * Do your init work in this method, it well be call when processor has been load.
     *
     * @param context ctx
     */
    override fun init(context: Context) {
        mContext = context

        XLog.d("init" + context.toString(), 100)
    }

    private fun isLogin(): Boolean {
        val token = TokenManager.getInstance().token
        return !TextUtils.isEmpty(token)
    }

    // the rxbus event from BaseActivity.onLoginSuccess
    @Subscribe(
            thread = EventThread.MAIN_THREAD
    )
    fun onLoginSuccess(loginEvent: SuccessLoginEvent) {
        if (callback != null && postcard != null) {
            callback?.onContinue(postcard!!)
        }
        cleanUp()
    }

    @Subscribe(
            thread = EventThread.MAIN_THREAD
    )
    fun onLoginFail(loginEvent: FailLoginEvent) {
        cleanUp()
    }

    @Subscribe(
            thread = EventThread.MAIN_THREAD
    )
    fun onLoginFail(loginEvent: CancelLoginEvent) {
        cleanUp()
    }

    private fun cleanUp() {
        try {
            LoginEventBus.instance.unregister(this@LoginInterceptor)
        } catch (ex: Exception) {
            // IllegalArgumentException maybe thrown if the bus is already unsubscribed, which we do not care
            // in any exception we do not crash
            XLog.e("e: ", ex, 10)
        }

        callback = null
        postcard = null
    }
}
